package com.lcc.lynx.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.lcc.lynx.common.exception.SystemException;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * Json工具类
 */
public class JsonUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();
    static {
        // 为Null时不序列化
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 允许单引号
        MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 允许不带引号的字段名称
        MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 设置时区和日期格式
        MAPPER.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        MAPPER.setDateFormat(new SimpleDateFormat(DateUtil.TF));
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 遇到空值处理为空串
        MAPPER.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
            @Override
            public void serialize(Object value, JsonGenerator jgen,
                                  SerializerProvider provider) throws IOException, JsonProcessingException {
                jgen.writeString("");
            }
        });
    }

    private JsonUtil() {

    }

    /**
     * 对象转JSON字符串
     *
     * @param obj Java对象
     * @param <T> 静态方法泛型
     * @return JSON串
     */
    public static <T> String toJSONString(T obj) {
        try {
            return MAPPER.writeValueAsString(obj);
        }catch (JsonProcessingException e){
            throw new SystemException("JSON转换异常", e);
        }
    }

    /**
     * JSON字符串转Java对象
     *
     * @param json JSON字符串
     * @param clz  Class<T>
     * @param <T>  <T> 静态方法泛型
     * @return Java对象
     * @throws IOException JSON反序列化异常
     */
    public static <T> T parseObject(String json, Class<T> clz) throws IOException {
        return MAPPER.readValue(json, clz);
    }

    /**
     * JSON字符串转Java对象
     * @param json
     * @param collectionClass 泛型的Collection
     * @param elementClasses 元素类
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> T parseObject(String json, Class<?> collectionClass, Class<?>... elementClasses) throws IOException {
        return MAPPER.readValue(json, getCollectionType(collectionClass, elementClasses));
    }

    /**
     * JSON字符串转Java对象
     * @param json
     * @param javaType
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> T parseObject(String json, JavaType javaType) throws IOException {
        return MAPPER.readValue(json, javaType);
    }

    /**
     * 获取泛型的Collection Type
     * List<T>、Set<T>、Map<String, T>
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     * @since 1.0
     */
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
}
